/** ==================================================================================== **/
/** 			Funzioni di utilità per manipolare il formato delle geometrie 			 **/
/** ==================================================================================== **/

BootApplication.service("olFormatService", [ '$log', function( log ) {
		
	/**
	 * Constructor
	 */
	this.formatter = {
	   /**
		* Geometry format per leggere e scrivere dati nel formato WellKnownText (WKT).
	    */
	   WKT: new ol.format.WKT(),
	   /**
		* Geometry format per leggere e scrivere dati nel formato GeoJSON.
	    */
	   GEO_JSON: new ol.format.GeoJSON()
	};
	     
	/**
	 * Ritorna la geometry come una WKT string.
	 * 
	 * @param {@link ol.geom.Geometry} geomerty	
	 * 
	 * Returns: 
	 * 		{@link String} WKT string | null. 
	 */
	this.olWktTransorm = function(geometry) { 
		try{
	       if(geometry != null)		
	       	  return this.formatter.WKT.writeGeometry(geometry);
	       else
	       	  return null;
	    }catch(e){
	   	  log.error(e);
	      return null;
	   }
	}// close olWktTransorm
	
	/**
	 * Ritorna la geometry dalla stringa WKT.
	 * 
	 * @param {@link String} wkt, WKT string	
	 * @param {@link ol.proj.ProjectionLike} dataProjection, Projection in cui i dati sono letti
	 * @param {@link ol.proj.ProjectionLike} featureProjection, Projection della geometria della feature
	 * 
	 * Returns:
	 * 		{@link ol.geom.Geometry} Geometry | null. 
	 */
	 this.olReadGeometryToWkt = function(wkt, dataProjection, featureProjection){
		 try{
		    var formatter = new ol.format.WKT();
		    	
		    if(wkt != null && !angular.equals(wkt, ""))		
		    	return this.formatter.WKT.readGeometry(wkt, {"dataProjection": dataProjection, "featureProjection": featureProjection});
		    else
		    	return null;
		 }catch(e){
			log.error(e);
		    return null;
		 }
	 }// close olReadFeatureToWkt
	 
	/**
	 * Ritorna la feature dalla stringa WKT.
	 * 
	 * @param {@link String} wkt, WKT string	
	 * @param {@link ol.proj.ProjectionLike} dataProjection, Projection in cui i dati sono letti
	 * @param {@link ol.proj.ProjectionLike} featureProjection, Projection della geometria della feature
	 * 
	 * Returns:
	 * 		{@link ol.Feature} Feature | null. 
	 */
	 this.olReadFeatureToWkt = function(wkt, dataProjection, featureProjection){
		 try{
		    var formatter = new ol.format.WKT();
		    	
		    if(wkt != null)		
		    	return this.formatter.WKT.readFeature(wkt, {"dataProjection": dataProjection, "featureProjection": featureProjection});
		    else
		    	return null;
		 }catch(e){
			log.error(e);
		    return null;
		 }
	 }// close olReadFeatureToWkt
	 
	 /**
	  * Ritorna la feature dalla string GeoJson.
	  * 
	  * @param {@link String} geoJson, GeoJson string	
	  * @param {@link ol.proj.ProjectionLike} dataProjection, Projection in cui i dati sono letti
	  * @param {@link ol.proj.ProjectionLike} featureProjection, Projection della geometria della feature
	  * 
	  * Returns: 
	  * 	 {@link ol.Feature} Feature | null. 
	  */
	 this.olReadFeatureToGeoJson = function(geoJson, dataProjection, featureProjection){
		 try{
			 if(geoJson != null)		
				 return this.formatter.GEO_JSON.readFeature(geoJson, {"dataProjection": dataProjection, "featureProjection": featureProjection});
		   	 else
		   		 return null;
		 }catch(e){
			log.error(e);
		    return null;
		 }
	 }// close olReadFeatureToGeoJson
	 
	 /**
	  * Ritorna le features dalla stringa GeoJson.
	  * 
	  * @param {@link String} geoJson, GeoJson string	
	  * @param {@link ol.proj.ProjectionLike} dataProjection, Projection in cui i dati sono letti
	  * @param {@link ol.proj.ProjectionLike} featureProjection, Projection della geometria della feature
	  * 
	  * Returns: 
	  * 	 {@link Array.<ol.Feature>} Features | null. 
	  */
	 this.olReadFeaturesToGeoJson = function(geoJson, dataProjection, featureProjection){
		 try{
			 if(geoJson != null)		
				 return this.formatter.GEO_JSON.readFeatures(geoJson, {"dataProjection": dataProjection, "featureProjection": featureProjection});
		   	 else
		   		 return null;
		 }catch(e){
			log.error(e);
		    return null;
		 }
	 }// close olReadFeaturesToGeoJson
	 
	 /**
	  * Ritorna un ol.Coordinate (senza modificare i punti originali), ma convertendo la longitudine e la latitudine dalla proiezione di origine 
	  * a quella di destinazione.
	  * 
	  * @param {@link Double} lon	
	  * @param {@link Double} lat
	  * @param {#link ol.proj.ProjectionLike} source
	  * @param {#link ol.proj.ProjectionLike} destination
	  * 
	  * Returns: 
	  * 	 {@link ol.Coordinate} Coordinate | null. 
	  */
	 this.olProjTransorm = function(lon, lat, sourceProjection, destProjection){
		 try{
			 if(lon != null && lat != null && sourceProjection != null && destProjection != null){
				return new ol.proj.transform([lon, lat], sourceProjection, destProjection);
			 }
			 else
				return null;
		 }catch(e){
			 log.error(e);
			 return null;
		 }
	 }// close olProjTransorm
	 
	 /**
	  * Transforms an extent from source projection to destination projection. This returns a new extent (and does not modify the original).
	  * 
	  * @param {@link ol.Extent{Array.<number>} Un array di numeri: [minx, miny, maxx, maxy].
	  * @param {#link ol.proj.ProjectionLike} source
	  * @param {#link ol.proj.ProjectionLike} destination
	  * 
	  * Returns: 
	  * 	 {@link ol.Extent} The transformed extent.
	  */
	 this.olProjTransformExtent = function(extent, sourceProjection, destProjection){
		 try{
			 if(extent != null && sourceProjection != null && destProjection != null){
				 return new ol.proj.transformExtent(extent, sourceProjection, destProjection);
			 }
			 else
				return null;
		 }catch(e){
			log.error(e);
		    return null;
		 }
	 }// close olProjTransformExtent
	 
	 /**
	  * Ritorna la geometria del punto.
	  * 
	  * @param {@link ol.Coordinate} coordinates.
	  * @param {@link ol.geom.GeometryLayout} layout
	  * 		  
	  * NOTA: 
	  *  ol.geom.GeometryLayout{string}
	  *   Il layout di coordinate per geometrie, che indica se un 3° o 4 ° Z ('Z') o la misura ('M') coordinate è disponibile. 
	  *   I valori supportati sono 'XY', 'XYZ', 'XYM', 'XYZM'.
	  * 
	  * Returns:  
	  * 	  {@link ol.geom.Point} Coordinate | null. 
	  */
	 this.olCoordinateToPoint = function (coordinates, layout){
		 try{
		 	 
		 	return new ol.geom.Point(coordinates, layout);
		  
		 }catch(e){
			 log.error(e);
			 return null;
		 }
	 }// close olCoordinateToPoint
	 
	 /**
	  * Dato il codice del formato delle feature, ritorna il corrispondente ol.format.Feature
	  * 
	  * @param {@link String} formato (Es: GeoJson, ecc...)
	  */
	 this.trasformInOlFormat = function(formato){
		 
		 var toReturn = null;
			
		 switch (formato) {
			 /* Feature format for reading and writing data in the EsriJSON format. */
			 case "EsriJSON": { toReturn = new ol.format.EsriJSON();}
			 /* Feature format for reading and writing data in the GeoJSON format. */
			 case "GeoJSON": { toReturn = new ol.format.GeoJSON();}
			 /* Feature format for reading data in the TopoJSON format. */
			 case "TopoJSON": { toReturn = new ol.format.TopoJSON;}
			 /* Feature format for *.igc flight recording files. */
			 case "IGC": { toReturn = new ol.format.IGC();}
			 /* Feature format for reading and writing data in the Encoded Polyline Algorithm Format. */
			 case "Polyline": { toReturn = new ol.format.Polyline();}
			 /* Geometry format for reading and writing data in the WellKnownText (WKT) format. */
			 case "WKT": { toReturn = new ol.format.WKT();}
			 /*
			  * Feature format for reading and writing data in the WFS format. By default, supports WFS version 1.1.0. You can pass a GML format as option 
			  * if you want to read a WFS that contains GML2 (WFS 1.0.0). Also see ol.format.GMLBase which is used by this format.
			  */
			 case "WFS": { toReturn = new ol.format.WFS();}
			 /* Format for reading WMSGetFeatureInfo format. It uses ol.format.GML2 to read features. */
			 case "WMSGetFeatureInfo": { toReturn = new ol.format.WMSGetFeatureInfo();}
				
			 default : toReturn = new ol.format.GeoJSON();
		};
			
		return toReturn;
	}// close trasformInOlFormat
	 
	/**
	 * Dato il codice del formato delle feature, ritorna il corrispondente ol.loadingstrategy
	 * 
	 * @param {@link String} strategy (Es: ALL, ecc...)
	 */
	this.transformInOlLoadingStrategy = function (strategy){
		var toReturn = null;
		
		switch (strategy) {
			/* Strategy function for loading all features with a single request. */
			case "ALL": { toReturn = ol.loadingstrategy.all; break;}
			/* Strategy function for loading features based on the view's extent and resolution. */
			case "BBOX": { toReturn = ol.loadingstrategy.bbox; break;}
			/* Creates a strategy function for loading features based on a tile grid. */
			case "TILE": { toReturn = ol.loadingstrategy.tile; break;}
			
			default: {toReturn = ol.loadingstrategy.all; break;}
		}
		
		return toReturn;
	}// close transformInOlLoadingStrategy
	
	/**
	 * Restituisce le coordinate dell ol.geom.Point costruito a prtire dalla stringa WKT fornita in ingresso.
	 * 
	 * @param {@link String} wkt: rappresentazione WKT di una geometria di tipo ol.geom.Point
	 * 
	 * @return {@link ol.Coordinate} array coordinate (index 0: elemento longitudine, index 1: elemento latitudine)
	 */	
	this.getPointCoordinateFromWKT = function(wkt){
		try{
			return this.formatter.WKT.readGeometry(wkt).getCoordinates();
		}catch(e){
			log.error(e);
		    return null;
		}
    }//close getPointCoordinateFromWKT
    
}]); 
